package com.gg.dao.impl;

import com.gg.utils.JdbcUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;

/**
 * 基本DAO封装了对数据表的通用的操作增删改查
 * 提高了sql重用性，代码利用率，增强可扩展力
 */
public abstract class BaseDao {
    //使用DbUtils操作数据库的增删改查
    private QueryRunner queryRunner = new QueryRunner();

    /**
     * update() 用来执行：insert，pdate，delete语句
     * @param sql
     * @param args 可变长参数
     * @return 如果返回-1说明执行失败，其它表示影响行数
     */
    //封装了我的Eclipse里的/JDBCday22-2-28/src/com/atguigu/PreparedStatementTest.java中的update方法
    public int update(String sql,Object ... args){

        System.out.println("BaseDao 程序在【"+Thread.currentThread().getName()+"】中");

        Connection connection = JdbcUtils.getConnection();
        try {
            return queryRunner.update(connection,sql,args);
        } catch (SQLException e) {
            e.printStackTrace();
            //异常可以捕获，但是 一定往外抛，这样任何位置出现异常都能回滚事务！
            throw new RuntimeException(e);
        }/*finally {        //使用了事务就不能关闭连接了，因为后边的service,servlet还要用
            JdbcUtils.close(connection);
        }
        //return -1;*/
    }

    /**
     * 查询返回一个 javaBean的sql语句
     * @param type  返回的对象类型
     * @param sql   执行的sql语句
     * @param args  sql对应的参数值
     * @param <T>   返回类型的泛型,多表通用，多实体类通用
     * @return 返回一个
     */
    public <T> T queryForOne(Class<T> type,String sql,Object ... args){
        Connection connection = JdbcUtils.getConnection();
        try {
            return queryRunner.query(connection,sql,new BeanHandler<T>(type),args);
        } catch (SQLException e) {
            e.printStackTrace();
            //异常可以捕获，但是 一定往外抛，这样任何位置出现异常都能回滚事务！
            throw new RuntimeException(e);
        }/*finally {        //使用了事务就不能关闭连接了，因为后边的service,servlet还要用
            JdbcUtils.close(connection);
        }
        return null;*/
    }

    /**
     * 查询返回多个 javaBean的sql语句
     * @param type  返回的对象类型
     * @param sql   执行的sql语句
     * @param args  sql对应的参数值
     * @param <T>   返回类型的泛型
     * @return
     */
    //以下单行查询和多行查询封装了我的eclipse中的/JDBCday22-2-28/src/com/atguigu/PsCommonQuery.java
    public <T>List<T> queryForList(Class<T> type, String sql, Object ... args){
        Connection connection = JdbcUtils.getConnection();
        try {
            return queryRunner.query(connection,sql,new BeanListHandler<T>(type),args);
        } catch (SQLException e) {
            e.printStackTrace();
            //异常可以捕获，但是 一定往外抛，这样任何位置出现异常都能回滚事务！
            throw new RuntimeException(e);
        }/*finally {
            JdbcUtils.close(connection);
        }
        return null;*/
    }

    /**
     * 执行返回一行一列的SQL语句
     * @param sql
     * @param args
     * @return
     */
    public Object queryForSingleValue(String sql, Object ... args){
        Connection connection = JdbcUtils.getConnection();
        try {
            Object object = queryRunner.query(connection, sql, new ScalarHandler(), args);
            return object;
        } catch (SQLException e) {
            e.printStackTrace();
            //异常可以捕获，但是 一定往外抛，这样任何位置出现异常都能回滚事务！
            throw new RuntimeException(e);
        }/*finally {        //使用了事务就不能关闭连接了，因为后边的service,servlet还要用
            JdbcUtils.close(connection);
        }
        return null;*/
    }

}
